///////////////////////////////////////////////////////////////////////////

#ifndef _AUDIOTRACK_H_
#define _AUDIOTRACK_H_

///////////////////////////////////////////////////////////////////////////

#include <vector>
#include <boost/circular_buffer.hpp>
#include <portaudiocpp/PortAudioCpp.hxx>
#include "fft.h"

///////////////////////////////////////////////////////////////////////////


/*  Stereo audio track
*
*   @author Roman Pasechnik
*   @since  Jan 05, 2009
*   @since  Jan 05, 2009
*/
class AudioTrack
{
///////////////////////////////////////////////////////////////////////////

public:

///////////////////////////////////////////////////////////////////////////


    /** [Utility type]: Amplitudes of one audio channel */
    typedef std::vector<short> Amplitudes;


    /** [Utility type]: Spectrum */
    typedef std::vector<complex> Spectrum;


	/** [Utility type]: Frequency amplitudes */
	typedef std::vector<double> FreqAmplitudes;


    /** Read the track into memory */
    virtual bool Read() = 0;


    /** Read the track into memory */
    bool DetectBeat();


	/** Frequency selected beat detection */
	bool DetectBeatFreq();


    void Play();


///////////////////////////////////////////////////////////////////////////

protected:

///////////////////////////////////////////////////////////////////////////


    /** Constructor */
    AudioTrack();


///////////////////////////////////////////////////////////////////////////


    /** Track rate */
    long m_Rate;


    /** Number of channels */
    int m_Channels;


    /** Encoding */
    int m_Encoding;


///////////////////////////////////////////////////////////////////////////


    /** Signal amplitudes of left and right audio channels */
    Amplitudes m_BothChannels;


    /** Signal amplitudes of left audio channel */
    Amplitudes m_LeftChannel;


    /** Signal amplitudes of right audio channel */
    Amplitudes m_RightChannel;


///////////////////////////////////////////////////////////////////////////

private:

///////////////////////////////////////////////////////////////////////////


    /** Computes instant sound energy */
    void ComputeInstantEnergy();


    /** Gets channel instant sound energy */
    double GetChannelEnergy( const Amplitudes& _channel ) const;


    /** Gets average energy from history */
    double GetAverageEnergy() const;


    /** Computes variance V */
    double ComputeVariance( double _averageEnergy ) const;


///////////////////////////////////////////////////////////////////////////


    /** Fast Fourier Transform */
    void FFT();


///////////////////////////////////////////////////////////////////////////


    /** Music spectrum */
    Spectrum m_Spectrum;


	/** Frequency amplitudes */
	FreqAmplitudes m_FreqAmplitudes;


    /** Instant sound energy */
    double m_InstantEnergy;


    /** Energy history */
    boost::circular_buffer<double> m_EnegyHistory;
    enum {  SUBBANDS_SIZE = 32,
		    HISTORY_SIZE = 43   };






    portaudio::AutoSystem m_AutoSys;
    portaudio::System& m_Sys;


    int PlayCallback( const void *inputBuffer,
                      void *outputBuffer,
                      unsigned long framesPerBuffer,
                      const PaStreamCallbackTimeInfo *timeInfo,
                      PaStreamCallbackFlags statusFlags );


///////////////////////////////////////////////////////////////////////////
};

#endif
